package Connector;

import javax.sql.rowset.WebRowSet;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

// response通过request拿到URI，再定位文件，通过buffer读取文件，写入response的outputStream
public class Response {

    private static final int BUFFER_SIZE = 2048;

    Request request;

    OutputStream output;
    // 每个流只能是输入流或输出流的一种，不能同时具备两个功能，输入流只能进行读操作，对输出流只能进行写操作。
    // 在一个数据传输通道中，如果既要写入数据，又要读取数据，则要分别提供两个流。
    // 流不需要关闭，request的input流，response的output流，只要server运行就一直存在

    public Response(OutputStream output) {
        this.output = output;
    }

    // 传入request
    public void setRequest(Request request) {
        this.request = request;
    }

    // 创建file对象，写入状态行，写入静态资源
    public void sendStaticResource() throws IOException{
        // 在指定目录和文件名下新建文件
        File file = new File(ConnectorUtils.WEB_ROOT, request.getRequestURI());
        // TODO new File是打开文件还是新建文件???

        try {
            write(file, HttpStatus.SC_OK);
            System.out.println("Response is sending static resources as 'OK'...");
        } catch (IOException e) {
            // 如果出错就生成状态行和写入404.html
            // 有点类似if-else
            write(new File(ConnectorUtils.WEB_ROOT, "404.html"), HttpStatus.SC_NOT_FOUND);
            // TODO 为什么这里不用抛出异常???
        }
    }

    // 把file的内容写入output
    public void write(File file, HttpStatus status) throws IOException {
        // try-with-resource; 放在try()里面，就不需要手动关闭了
        // 当一个外部资源的句柄对象（比如FileInputStream对象）实现了AutoCloseable接口，就可以使用try-with-resource
        try (FileInputStream fis = new FileInputStream(file)) {
            // TODO 为什么需要fis??
                // fis把file写入buffer，buffer再写入output
            // TODO 为什么用FileInputStream?
                // 因为要读入文件呀
            // TODO 可以用缓存流包起来吗？


            // 1. output先写入状态行
            System.out.println("Response is writing the status line into outputStream...");
            System.out.println("Reponse is calling ConnectorUtils...");
            output.write(ConnectorUtils.renderStatus(status).getBytes());


            byte[] buffer = new byte[BUFFER_SIZE];
            int length = 0;

            // 2. output再写入file
            while ((length = fis.read(buffer, 0, BUFFER_SIZE)) != -1) {
                // 从buffer的第0个byte开始向output写入length长度的bytes
                // 就是每次把buffer全部写入output
                output.write(buffer, 0, length);
            }
            System.out.println("Response is writing the file into outputStream...");
        } catch (IOException e) {
            System.out.println("If anything wrong...");
        }
        // TODO 这里try-with-resource为什么没有catch{}?
            // 这里不需要处理。因为上面调用write()的地方已经有try-catch处理了
            // TODO 在这里处理为什么不行？？？不知道，解决不了。
        // TODO 这里不使用try-with-resource，手动关闭fis，是不是一样的?
        // TODO 重复刷新几次，就会socketException，为什么???
    }
}
